package pers.cz.netty.protocal;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @program: JefLogTail
 * @description: UDP解码
 * @author: Cheng Zhi
 * @create: 2023-03-29 15:09
 **/
public class UdpMessageDecoder extends MessageToMessageDecoder<DatagramPacket> {

    private static final Logger log = LoggerFactory.getLogger(UdpMessageDecoder.class);
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket, List<Object> list) throws Exception {
        ByteBuf byteBuf = datagramPacket.content();
        // 解密魔数
        byte[] bytes = new byte[8];
        byteBuf.readBytes(bytes);
        String magicNum = new String(bytes, StandardCharsets.UTF_8);

        if (!ProtocalConst.POCKET_MAGIC_NUM.equals(magicNum)) {
            log.error("未知数据包，magicNum=" + magicNum );
            return;
        }

        // 解密消息类型
        byte msgType = byteBuf.readByte();

        final MsgType type = MsgType.getMsgType(msgType);
        if (type == null) {
            log.error("未知操作类型：" + msgType);
            return;
        }

        Message msg = new Message();
        msg.setMsgType(type);

        // 解密消息附件
        short attachmentSize = byteBuf.readShort();	// 读取附件长度
        for (short i = 0; i < attachmentSize; i++) {
            int keyLength = byteBuf.readInt();	// 读取键长度和数据
            CharSequence key = byteBuf.readCharSequence(keyLength, Charset.defaultCharset());
            int valueLength = byteBuf.readInt();	// 读取值长度和数据
            CharSequence value = byteBuf.readCharSequence(valueLength, Charset.defaultCharset());
            msg.addAttachment(key.toString(), value.toString());
        }


        // 读取消息长度
        long contentLenth = byteBuf.readLong();

        msg.setContentLength(contentLenth);
        if(contentLenth > 0){
            // 读取主体内容
            byte[] contents = new byte[(int) contentLenth];
            byteBuf.readBytes(contents,0, (int) contentLenth);
            ByteArrayInputStream bis=new ByteArrayInputStream(contents);
            ObjectInputStream ois=new ObjectInputStream(bis);
            msg.setContent(ois.readObject());
        }

        list.add(msg);
    }
}
